home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Misc / Wood.0.72 / Sources / TreeView.m < prev    next >
Encoding:
Text File  |  1995-08-28  |  12.3 KB  |  498 lines

  1.  
  2. #import "Utilities.h"
  3. #import "TreeView.h"
  4.  
  5. #define LEFTARROWKEY    172
  6. #define RIGHTARROWKEY    174
  7. #define UPARROWKEY        173
  8. #define DOWNARROWKEY    175
  9. #define PUSHKEY            0x3
  10. #define BACKSPACEKEY    0x7f
  11.  
  12. @interface TreeView(PrivateMethods)
  13.  
  14. - updateCanvasPos:(NXCoord)xPos :(NXCoord)yPos;
  15.  
  16. @end
  17.  
  18. @implementation TreeView
  19.  
  20. - initFrame:(const NXRect *)frameRect
  21. {
  22.     [super initFrame:frameRect];
  23.     xTimes = 1;
  24.     yTimes = 1;
  25.     canvasRect = *frameRect;
  26.     canvasPath = nil;
  27.     [self updateCanvasPos:0 :0];
  28.     [[self setClipping:NO] setFlipped:YES];
  29.     linkPath = nil;
  30.     hitPath = nil;
  31.     agent = nil;
  32.     nodeList = [[List allocFromZone:[self zone]] init];
  33.     pbConversion = NO;
  34.     pbTree = nil;
  35.     return self;
  36. }
  37.  
  38. - free
  39. {
  40.     if(linkPath)
  41.         [linkPath free];
  42.     if(hitPath)
  43.         [hitPath free];
  44.     [nodeList free];
  45.     return [super free];
  46. }
  47.  
  48. - (BOOL)lockFocus
  49. {
  50.        BOOL aBOOL;
  51.        float rot,gruen,blau;
  52.    
  53.        if(NXDrawingStatus == NX_DRAWING){
  54.         aBOOL = [super lockFocus];
  55.         PScurrentlinewidth(&drawState.linewidth);
  56.         PScurrentrgbcolor(&rot,&gruen,&blau);
  57.         drawState.color = NXConvertRGBToColor(rot,gruen,blau);
  58.         drawState.font = nil;
  59.         return aBOOL;
  60.        } else
  61.         return [super lockFocus];
  62. }
  63.  
  64. - drawSelf:(const NXRect *)r :(int)count
  65. {      
  66.        if(count == 1){ 
  67.          [self drawYourSelf:r];
  68.        } else {
  69.           [self drawYourSelf:&r[1]];
  70.           [self drawYourSelf:&r[2]];
  71.        }                                       
  72.        return self;            
  73. }
  74.  
  75. - drawYourSelf:(const NXRect *)r
  76. {  
  77.     id tree;
  78.     int i,j;
  79.  
  80.        PSsetgray(NX_WHITE);
  81.     NXRectFill(r);
  82.     drawState.color = NX_COLORWHITE;
  83.     if(NXDrawingStatus == NX_DRAWING){
  84.         PSrectviewclip(r->origin.x,r->origin.y,r->size.width,r->size.height);       
  85.         PSsetgray(NX_LTGRAY);
  86.         PSsetlinewidth(0.15);
  87.         drawState.color = NX_COLORLTGRAY;
  88.         drawState.linewidth = 0.15;
  89.         for(i = 0;i <= xTimes;i++)
  90.             for(j = 0;j <= yTimes;j++){
  91.                 [self updateCanvasPos:i * NX_WIDTH(&canvasRect) :j * NX_HEIGHT(&canvasRect)];
  92.                 [canvasPath send:dps_ustroke cached:YES];
  93.             }
  94.     }
  95.     if(!pbConversion)
  96.         tree = [agent tree];
  97.     else
  98.         tree = pbTree;
  99.     if(tree)
  100.         [self drawTree:tree inRect:r];
  101.     if(NXDrawingStatus == NX_DRAWING)
  102.           PSinitviewclip();                                   
  103.        return self;            
  104. }
  105.  
  106. - drawTree:tree inRect:(const NXRect *)r
  107. {
  108.     int i;
  109.     BOOL knobs, attachments;
  110.  
  111.     [tree layout];        
  112.     if(!linkPath)
  113.         linkPath = [[UPath allocFromZone:[self zone]] init];
  114.     [linkPath resetFill]; 
  115.     [nodeList empty];
  116.     if(NXDrawingStatus == NX_PRINTING)
  117.         [tree involved:NULL addTo:nodeList link:linkPath];
  118.     else
  119.         [tree involved:r addTo:nodeList link:linkPath];
  120.     for(i = 0; i < [nodeList count];i++)
  121.         [[nodeList objectAt:i] drawNodeShadow:&drawState];
  122.     if([tree child] && ![tree zipped]){
  123.         PSsetgray(NX_BLACK);
  124.         drawState.color = NX_COLORBLACK;
  125.         PSsetlinewidth(0.15);
  126.         drawState.linewidth = 0.15;
  127.         [linkPath send:dps_ustroke cached:NO];
  128.     }
  129.     for(i = 0; i < [nodeList count];i++)
  130.         [[nodeList objectAt:i] drawNodeEnding:&drawState];
  131.     for(i = 0; i < [nodeList count];i++)
  132.         [[nodeList objectAt:i] drawNodeFill:&drawState];
  133.     if(NXDrawingStatus == NX_DRAWING){
  134.         knobs = YES;
  135.         attachments = [agent showMarker];
  136.     } else
  137.         knobs = attachments = NO;
  138.     for(i = 0; i < [nodeList count];i++)
  139.         [[nodeList objectAt:i] drawNodeOutline:&drawState knobs:knobs];
  140.     for(i = 0; i < [nodeList count];i++)
  141.         [[nodeList objectAt:i] drawNodeCellsInView:self attachments:attachments];
  142.     return self;    
  143. }    
  144.  
  145. - mouseDown:(NXEvent *)event
  146. {
  147.     NXPoint p;
  148.     NXRect redrawRect, textFrame;
  149.     NXSize maxTextSize;
  150.     id selectedNode,lastSelected,tree;
  151.     id retval, fe = nil;
  152.     BOOL hitAttach, fieldResponder = NO;
  153.  
  154.     p = event->location; 
  155.     [self convertPoint:&p fromView:nil];
  156.     [window disableFlushWindow];
  157.     [self  lockFocus];
  158.         tree = [agent tree];
  159.         if(tree){
  160.             if(!hitPath)
  161.                 hitPath = [[HitPath allocFromZone:[self zone]] init];
  162.             [hitPath movePathToPoint:&p];
  163.             selectedNode = [tree hit:hitPath];
  164.             if(selectedNode){
  165.                 lastSelected = [agent declareSelection:selectedNode];
  166.                 if(selectedNode != lastSelected){
  167.                     [selectedNode getBounds:&redrawRect];
  168.                     [self drawSelf:&redrawRect :1];
  169.                     [self scrollRectToVisible:&redrawRect];
  170.                     if(lastSelected){
  171.                         [lastSelected setSelected:YES];
  172.                         [lastSelected getBounds:&redrawRect];
  173.                         [lastSelected setSelected:NO];
  174.                         [self drawSelf:&redrawRect :1];
  175.                     }
  176.                 }
  177.                 if(event->data.mouse.click >= 2){
  178.                     [window endEditingFor:self];
  179.                     fe = [window getFieldEditor:YES for:self];
  180.                     [fe setFont:[selectedNode font]];
  181.                     [fe setCharFilter:NXFieldFilter];
  182.                     [fe setFontPanelEnabled:NO];
  183.                     [fe setMonoFont:YES];
  184.                     [fe setOpaque:YES];
  185.                     [selectedNode getTextFrame:&textFrame];
  186.                     [fe setMinSize:&(textFrame.size)];
  187.                     maxTextSize.width = bounds.size.width;
  188.                     maxTextSize.height = textFrame.size.height;
  189.                     [fe setMaxSize:&maxTextSize];
  190.                     [fe setFrame:&textFrame];
  191.                     [fe setHorizResizable:YES];
  192.                     [fe setText:[selectedNode label]];
  193.                     [fe selectAll:self];
  194.                     [fe setAlignment:NX_CENTERED];
  195.                     [fe unscript:self];
  196.                     [fe setVertResizable:NO];
  197.                     [fe setDelegate:selectedNode];
  198.                     [self addSubview:fe];
  199.                     p.x = textFrame.origin.x;
  200.                     p.y = textFrame.origin.y;
  201.                     [self convertPoint:&p toView:nil];
  202.                     event->location = p;
  203.                     [fe mouseDown:event];
  204.                     fieldResponder = YES;
  205.                 }
  206.             } else if([agent showMarker]){
  207.                 selectedNode = [tree hitAttachment:&p :&hitAttach];            
  208.                 if(selectedNode){
  209.                     [window reenableFlushWindow];
  210.                     if(hitAttach)
  211.                         retval = [selectedNode activateAttachment:event inView:self];
  212.                     else
  213.                         retval = [selectedNode activateSound:event inView:self];
  214.                     [window disableFlushWindow];
  215.                     if(retval){
  216.                         lastSelected = [agent declareSelection:selectedNode];
  217.                         if(selectedNode != lastSelected){
  218.                             [selectedNode getBounds:&redrawRect];
  219.                             [self drawSelf:&redrawRect :1];
  220.                             if(lastSelected){
  221.                                 [lastSelected setSelected:YES];
  222.                                 [lastSelected getBounds:&redrawRect];
  223.                                 [lastSelected setSelected:NO];
  224.                                 [self drawSelf:&redrawRect :1];
  225.                             }
  226.                         }
  227.                     }
  228.                 } else {
  229.                     lastSelected = [agent declareSelection:nil];
  230.                     if(lastSelected){
  231.                         [lastSelected setSelected:YES];
  232.                         [lastSelected getBounds:&redrawRect];
  233.                         [lastSelected setSelected:NO];
  234.                         [self drawSelf:&redrawRect :1];
  235.                     }
  236.                 }
  237.             }
  238.         }
  239.     [self  unlockFocus];
  240.     [window reenableFlushWindow];
  241.     [window  flushWindow];
  242.     if(fieldResponder)
  243.         [window makeFirstResponder:fe];
  244.     else
  245.         [window makeFirstResponder:self];
  246.     return self;
  247. }
  248.  
  249. - keyDown:(NXEvent *)event
  250. {
  251.     id selectedNode = nil,lastSelected,tree,fe;
  252.     NXEvent *eptr = event;
  253.     NXRect redrawRect, textFrame;
  254.     NXSize maxTextSize;
  255.  
  256.     if(eptr->data.key.charSet == NX_SYMBOLSET){
  257.         lastSelected = [agent currentNode];
  258.         if(!lastSelected)
  259.             return self;
  260.         [window disableFlushWindow];
  261.         [self  lockFocus];
  262.         switch(eptr->data.key.charCode){
  263.             case LEFTARROWKEY:
  264.                 selectedNode = [lastSelected parent];
  265.             break;
  266.             case RIGHTARROWKEY:
  267.                 if(![lastSelected zipped])
  268.                     selectedNode = [lastSelected child];
  269.             break;
  270.             case UPARROWKEY:
  271.                 tree = [lastSelected parent];
  272.                 if(tree){
  273.                     tree = [tree child];
  274.                     if(tree == lastSelected)
  275.                         selectedNode = nil;
  276.                     else {
  277.                         while([tree sibling] != lastSelected)
  278.                             tree = [tree sibling];
  279.                         selectedNode = tree;
  280.                     }
  281.                 } else
  282.                     selectedNode = nil;
  283.             break;
  284.             case DOWNARROWKEY:
  285.                 selectedNode = [lastSelected sibling];
  286.             break;
  287.             default:
  288.             break;
  289.         }
  290.         if(selectedNode){
  291.             [agent declareSelection:selectedNode];
  292.             [selectedNode getBounds:&redrawRect];
  293.             [self drawSelf:&redrawRect :1];
  294.             [self scrollRectToVisible:&redrawRect];
  295.             [lastSelected setSelected:YES];
  296.             [lastSelected getBounds:&redrawRect];
  297.             [lastSelected setSelected:NO];
  298.             [self drawSelf:&redrawRect :1];
  299.         }
  300.         [self  unlockFocus];
  301.         [window reenableFlushWindow];
  302.         [window  flushWindow];
  303.         [window makeFirstResponder:self];
  304.     } else if(eptr->data.key.charSet == NX_ASCIISET && eptr->data.key.charCode == PUSHKEY){
  305.         lastSelected = [agent currentNode];
  306.         if(!lastSelected)
  307.             return self;
  308.         [self  lockFocus];
  309.         [window endEditingFor:self];
  310.         fe = [window getFieldEditor:YES for:self];
  311.         [fe setFont:[lastSelected font]];
  312.         [fe setCharFilter:NXFieldFilter];
  313.         [fe setFontPanelEnabled:NO];
  314.         [fe setMonoFont:YES];
  315.         [fe setOpaque:YES];
  316.         [lastSelected getTextFrame:&textFrame];
  317.         [fe setMinSize:&(textFrame.size)];
  318.         maxTextSize.width = bounds.size.width;
  319.         maxTextSize.height = textFrame.size.height;
  320.         [fe setMaxSize:&maxTextSize];
  321.         [fe setFrame:&textFrame];
  322.         [fe setHorizResizable:YES];
  323.         [fe setText:[lastSelected label]];
  324.         [fe setAlignment:NX_CENTERED];
  325.         [fe unscript:self];
  326.         [fe setVertResizable:NO];
  327.         [fe setDelegate:lastSelected];
  328.         [self addSubview:fe];
  329.         [fe selectAll:self];
  330.         [self  unlockFocus];
  331.         [window  flushWindow];
  332.         [window makeFirstResponder:fe];
  333.     } else if(eptr->data.key.charSet == NX_ASCIISET && eptr->data.key.charCode == BACKSPACEKEY)
  334.         [agent delete:self];
  335.     return self;
  336. }
  337.  
  338. - (BOOL)checkResize:(const NXRect *)r for:tree
  339. {
  340.     NXRect treeBounds;
  341.     NXCoord dlx, dly, dux, duy;
  342.     BOOL result = NO;
  343.     NXPoint p;
  344.     int tx,ty;
  345.  
  346.     [tree layout];
  347.     [tree getTreeBounds:&treeBounds lowerWidth:&dlx lowerHeight:&dly];
  348.     dux = NX_WIDTH(&treeBounds) - dlx; 
  349.     duy = NX_HEIGHT(&treeBounds) - dly;
  350.     [self convertRect:&treeBounds toView:superview];
  351.     if(r){
  352.         [self sizeTo:NX_WIDTH(r) :NX_HEIGHT(r)];
  353.         canvasRect = *r;
  354.         xTimes = yTimes = 1;
  355.         result = YES;
  356.     }
  357.     tx = ceil(NX_WIDTH(&treeBounds) / NX_WIDTH(&canvasRect));
  358.     ty = ceil(NX_HEIGHT(&treeBounds) / NX_HEIGHT(&canvasRect));
  359.     if(ty != yTimes || tx != xTimes){
  360.         xTimes = tx;
  361.         yTimes = ty;
  362.         [self sizeTo:NX_WIDTH(&canvasRect) * xTimes :NX_HEIGHT(&canvasRect) * yTimes];
  363.         result = YES;
  364.     }
  365.     if(xTimes == 1)
  366.         p.x = dlx + (NX_WIDTH(&bounds) - dlx - dux) / 2;
  367.     else
  368.         p.x = dlx + 3;
  369.     if(yTimes == 1)
  370.         p.y = dly + (NX_HEIGHT(&bounds) - dly - duy) / 2;
  371.     else
  372.         p.y = dly + 3;
  373.     [tree setPositionTo:&p];
  374.     return result;
  375. }
  376.  
  377. - setAgent:aAgent
  378. {
  379.     agent = aAgent;
  380.     return self;
  381. }
  382.  
  383. - agent
  384. {
  385.     return agent;
  386. }
  387.  
  388. - writePSToStream:(NXStream *)stream usingTree:aTree
  389. {
  390.     NXRect bbox;
  391.     NXCoord dl, du;
  392.  
  393.     if(stream){
  394.         pbConversion = YES;
  395.         pbTree = aTree;
  396.         [aTree getTreeBounds:&bbox lowerWidth:&dl lowerHeight:&du];
  397.         [self copyPSCodeInside:&bbox to:stream];
  398.         pbConversion = NO;
  399.         pbTree = nil;
  400.     }
  401.     return self;
  402. }
  403.  
  404. - (BOOL)zoomTo:(float)zoomX :(float)zoomY
  405. {
  406.     if(agent)
  407.         [agent setDocScale:zoomX];
  408.     return NO;
  409. }
  410.  
  411. - (BOOL)acceptsFirstResponder
  412. {
  413.     return YES;
  414. }
  415.  
  416. - (int)canvasX
  417. {
  418.     return xTimes;
  419. }
  420.  
  421. - (int)canvasY
  422. {
  423.     return yTimes;
  424.  
  425. - (BOOL)knowsPagesFirst:(int *)firstPageNum last:(int *)lastPageNum
  426. {
  427.     *lastPageNum = xTimes * yTimes;
  428.     return YES;
  429. }
  430.  
  431. - (BOOL)getRect:(NXRect *)theRect forPage:(int)page
  432. {
  433.     int row, col;
  434.     
  435.     if(page < 1 || page > xTimes * yTimes)
  436.         return NO;
  437.     page--;
  438.     row = page / xTimes;
  439.     col = page % xTimes;
  440.     theRect->origin.x = col * NX_WIDTH(&canvasRect);
  441.     theRect->origin.y = row * NX_HEIGHT(&canvasRect);
  442.     theRect->size.width = NX_WIDTH(&canvasRect);
  443.     theRect->size.height = NX_HEIGHT(&canvasRect);
  444.     return YES;
  445. }
  446.  
  447. - printPSCode:sender
  448. {
  449.     float printScaleFactor;
  450.     
  451.     printScaleFactor = [[agent printInfo] scalingFactor];
  452.     if(printScaleFactor != 1)
  453.         [self scale:printScaleFactor :printScaleFactor];
  454.     [super printPSCode:sender];
  455.     if(printScaleFactor != 1)
  456.         [self scale: 1 / printScaleFactor :1 / printScaleFactor];
  457.     return self;
  458. }
  459.  
  460. @end
  461.  
  462.  
  463. @implementation TreeView(PrivateMethods)
  464.  
  465. - updateCanvasPos:(NXCoord)xPos :(NXCoord)yPos
  466. {
  467.     canvasRect.origin.x = xPos;
  468.     canvasRect.origin.y = yPos;
  469.     if(!canvasPath){
  470.         canvasPath = [[UPath allocFromZone:[self zone]] init];
  471.         [canvasPath moveto:canvasRect.origin.x :canvasRect.origin.y];
  472.         [canvasPath rlineto:canvasRect.size.width :0.0];
  473.         [canvasPath rlineto:0.0 :canvasRect.size.height];
  474.         [canvasPath rlineto:-canvasRect.size.width :0.0];
  475.         [canvasPath rlineto:0.0 :-canvasRect.size.height];
  476.     } else {
  477.         canvasPath->bbox[0] = canvasRect.origin.x;
  478.            canvasPath->bbox[1] = canvasRect.origin.y;
  479.         canvasPath->bbox[2] = canvasRect.origin.x + canvasRect.size.width;
  480.         canvasPath->bbox[3] = canvasRect.origin.y + canvasRect.size.height;
  481.         canvasPath->params[0] = canvasRect.origin.x;
  482.         canvasPath->params[1] = canvasRect.origin.y;
  483.         canvasPath->params[2] = canvasRect.size.width;
  484.         canvasPath->params[3] = 0.0;
  485.         canvasPath->params[4] = 0.0;
  486.         canvasPath->params[5] = canvasRect.size.height;
  487.         canvasPath->params[6] = -canvasRect.size.width;
  488.         canvasPath->params[7] = 0.0;
  489.         canvasPath->params[8] = 0.0;
  490.         canvasPath->params[9] = -canvasRect.size.height;
  491.     }
  492.     return self;
  493. }
  494.  
  495. @end
  496.  
  497.